﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using StockFinder.DataAccess;
using log4net;
using System.Globalization;
using StockFinder.Model;
using StockFinder.Services.Extractors.Yahoo;
using StockFinder.Model.Enumerations;
using StockFinder.Services.Engines.Yahoo;
using StockFinder.Services.ChartPatterns;
using StockFinder.Services.Extractors.IBD;
using System.Xml;
using System.Net;
using StockFinder.Services.Extractors;
//using StockFinder.Services.Extractors.Google;
using StockFinder.Services.FileManagement;
using StockFinder.Services.Indicators;
using System.Diagnostics;
using StockFinder.Services.Extractors.EODData;
using System.Threading.Tasks;
using System.Threading;
using System.Linq;
using StockFinder.Services.Extractors.SharePricesDotCom;

namespace Testharness
{
    public partial class Form1 : Form
    {
        private static readonly ILog _Log = LogManager.GetLogger(typeof(Form1));

        private SymbolDataAccess _SymbolDataAccess = new SymbolDataAccess();
        private DailyPriceDataAccess _DailyPriceDataAccess = new DailyPriceDataAccess();

        private IHistoricPricesExtractor _YahooPricesExtractor = new YahooHistoricPriceExtractor();

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            IndexUrlDataAccess indexUrlDataAccess = new IndexUrlDataAccess();
            List<IndexUrl> indexUrls = new List<IndexUrl>();
            List<Symbol> symbols = new List<Symbol>();

            ///* generate the index Urls */
            
            //IndexUrlGeneratorEngine urlsEngine = new IndexUrlGeneratorEngine();
            //List<string> urls = urlsEngine.Run();

            ///* save any new index urls */            

            //_Log.DebugFormat("Inserting Urls...");

            //foreach (string url in urls)
            //{
            //    IndexUrl indexUrl = new IndexUrl(){ Url = url};

            //    if (!indexUrlDataAccess.DoesIndexUrlExistByIndexUrl(indexUrl))
            //    {
            //        //save new index url
            //        indexUrlDataAccess.InsertIndexUrl(indexUrl);

            //        _Log.DebugFormat("IndexUrl: Inserted {0}", url);
            //    }
            //    else
            //    {
            //        _Log.DebugFormat("IndexUrl: {0} already exists", url);
            //    }
            //}

            ///* read index urls from database */  

            _Log.Debug("Reading IndexUrls from database...");

            indexUrls = indexUrlDataAccess.GetAllIndexUrls();

            _Log.DebugFormat("Read {0} IndexUrls from database", indexUrls.Count);

            ///* extract the symbols from urls */

            YahooSymbolExtractor symbolExtractorEngine = new YahooSymbolExtractor();

            _Log.Debug("Starting IndexUrl loop for symbol extraction...");

            int completed = 0;

            foreach (IndexUrl indexUrl in indexUrls)
            {
                _Log.DebugFormat("Calling '{0}'", indexUrl.Url);

                //get list of symbol names from url
                List<string> names = symbolExtractorEngine.ExtractSymbolsFromUrl(indexUrl.Url);

                _Log.DebugFormat("Extracted {0} names", names.Count);

                //loop the names
                foreach (string symbolName in names)
                {                    
                    //does it already exist?
                    if (!symbols.Exists(delegate(Symbol item) { return item.Name == symbolName; }))
                    {
                        //doesnt exist so create new one
                        Symbol newSymbol = new Symbol() { Name = symbolName };

                        //add to list
                        symbols.Add(newSymbol);

                        _Log.DebugFormat("Symbol {0}: added to collection", symbolName);
                    }
                    else
                    {
                        _Log.DebugFormat("Symbol {0}: already exists in collection", symbolName);
                    }
                }                

                _Log.InfoFormat("{0:#.##}%", decimal.Divide(completed++, indexUrls.Count) * 100);
            }

            ///* save any new symbols */

            SymbolDataAccess dataAccess = new SymbolDataAccess();
            List<Symbol> existingSymbols = new List<Symbol>();
            List<Symbol> newSymbols = new List<Symbol>();

            _Log.InfoFormat("Inserting Symbols in database...");

            foreach (Symbol symbol in symbols)
            {
                if (dataAccess.DoesSymbolExistByName(symbol))
                {
                    existingSymbols.Add(symbol);
                }
                else
                {
                    dataAccess.InsertSymbol(symbol);

                    newSymbols.Add(symbol);
                }
            }

            _Log.InfoFormat("Completed. {0} success, {1} failed", newSymbols.Count, existingSymbols.Count);
        }

        private void button2_Click(object sender, EventArgs e)
        {
            IndexUrlDataAccess dataAccess = new IndexUrlDataAccess();

            if (!dataAccess.DoesIndexUrlExistByIndexUrl(new IndexUrl() { Url = "test" }))
            {
                dataAccess.InsertIndexUrl(new IndexUrl() { Url = "test" });
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            SymbolDataAccess dataAccess = new SymbolDataAccess();

            if (!dataAccess.DoesSymbolExistByName(new Symbol() { Name = "test" }))
            {
                dataAccess.InsertSymbol(new Symbol() { Name = "test" });
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            _Log.Debug("Testing 123123");
        }

        private void button5_Click(object sender, EventArgs e)
        {
            /* test getting prices */

            DailyPriceDataAccess dataAccess = new DailyPriceDataAccess();

            DateTime dateFrom = new DateTime(2009,09,01);
            DateTime dateTo = new DateTime(2009,09,30);

            Symbol symbol = new Symbol() { Name = "MSFT", SymbolId = 26074 };

            YahooHistoricPriceExtractor priceExtractor = new YahooHistoricPriceExtractor();

            //get the prices extract data
            HistoricPricesExtract pricesExtract = priceExtractor.GetHistoricPrices(
                dateFrom,
                dateTo,
                symbol.Name);


            if (pricesExtract.HistoricPricesExtractResult == HistoricPricesExtractResult.SUCCESS)
            {
                foreach (DailyPrice dailyPrice in pricesExtract.DailyPrices)
                {
                    if (!dataAccess.DoesDailyPriceExistByDateAndSymbol(dailyPrice))
                    {
                        dataAccess.InsertDailyPrice(dailyPrice);
                    }
                }
            }
        }

        private void button6_Click(object sender, EventArgs e)
        {
            YahooHistoricPriceLoadRunEngine engine = new YahooHistoricPriceLoadRunEngine();

            DateTime dateFrom =    new DateTime(2007, 11, 1);
            DateTime dateTo =     new DateTime(2009, 11, 27);

            engine.Run(dateFrom, dateTo);
        }

        private void button7_Click(object sender, EventArgs e)
        {
            _Log.InfoFormat("Testing getting all symbols and prices...");

            SymbolDataAccess symbolsDataAccess = new SymbolDataAccess();

            _Log.InfoFormat("Loading symbols...");

            List<Symbol> symbols = symbolsDataAccess.GetAllSymbols();

            _Log.InfoFormat("Loaded {0} symbols", symbols.Count);

            DailyPriceDataAccess dailyPricesDataAccess = new DailyPriceDataAccess();

            DateTime dateFrom = new DateTime(2009,01,01);

            _Log.InfoFormat("Looping symbols");

            foreach (Symbol symbol in symbols)
            {
                _Log.InfoFormat("(Symbol) {0}:{1}", symbol.SymbolId, symbol.Name);

                dailyPricesDataAccess.GetAllDailyPricesBySymbolIdFromDate(symbol, dateFrom);
            }
        }

        private void button8_Click(object sender, EventArgs e)
        {
            _Log.InfoFormat("Testing applying flat base...");

            SymbolDataAccess symbolsDataAccess = new SymbolDataAccess();

            List<Symbol> symbols = symbolsDataAccess.GetAllSymbols();

            _Log.InfoFormat("Loaded {0} symbols", symbols.Count);

            DailyPriceDataAccess dailyPricesDataAccess = new DailyPriceDataAccess();

            DateTime dateFrom = new DateTime(2009, 01, 01);

            _Log.InfoFormat("Looping first 5000 symbols");

            for (int index = 0; index < 5000; index++)
            {
                Symbol symbol = symbols[index];

                _Log.InfoFormat("(Symbol) {0}:{1}", symbol.SymbolId, symbol.Name);

                dailyPricesDataAccess.GetAllDailyPricesBySymbolIdFromDate(symbol, dateFrom);
            }

            /* apply flat base */

            List<Symbol> flatBases = new List<Symbol>();

            //FlatBase flatBase = new FlatBase();

            //foreach (Symbol symbol in symbols)
            //{
            //    if (flatBase.DoesFit(symbol))
            //    {
            //        flatBases.Add(symbol);
            //    }
            //}

            //_Log.InfoFormat("Flat bases:");

            //foreach (Symbol symbol in flatBases)
            //{
            //    _Log.InfoFormat(symbol.Name);
            //}
        }

        private void button9_Click(object sender, EventArgs e)
        {
            int weekOfYear = CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(
                DateTime.Now,
                CultureInfo.CurrentCulture.DateTimeFormat.CalendarWeekRule,
                CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek);
        }

        private void button10_Click(object sender, EventArgs e)
        {
            SymbolDataAccess symbolController = new SymbolDataAccess();
            DateTime dateFrom = new DateTime(2009, 5, 1);
            symbolController.GetAllSymbolsAndPrices(dateFrom);
        }

        private void button11_Click(object sender, EventArgs e)
        {
            //get enough prices
            SymbolDataAccess symbolController = new SymbolDataAccess();
            DateTime dateFrom = new DateTime(2009, 5, 1);

            _Log.InfoFormat("Getting symbols and prices");

            List<Symbol> symbols = symbolController.GetAllSymbolsAndPrices(dateFrom);

            WeeklyFlatBaseChartPattern weeklyFlatBase = new WeeklyFlatBaseChartPattern();

            List<Symbol> flatBases = new List<Symbol>();

            _Log.InfoFormat("Applying pattern...");

            ChartPatternResult result;

            List<ChartPatternResult> results = new List<ChartPatternResult>();

            foreach (Symbol symbol in symbols)
            {
                //get result details
                result = weeklyFlatBase.Apply(symbol);

                if (result.DoesFit)
                {
                    //_Log.InfoFormat("Flat Base: {0} for {1}", symbol.Name, result.BaseLength);

                    results.Add(result);
                }
            }

            //sort the results
            results.Sort(new Comparison<ChartPatternResult>(
                    delegate(ChartPatternResult l, ChartPatternResult r)
                    {
                        return l.BaseLength.CompareTo(r.BaseLength);
                    }));

            foreach (ChartPatternResult baseresult in results)
            {
                _Log.InfoFormat("Flat Base: {0} for {1}", baseresult.Symbol.Name, baseresult.BaseLength);
            }
        }

        private void button12_Click(object sender, EventArgs e)
        {
            List<IndexUrl> indexUrls = new List<IndexUrl>();

            YahooSymbolIndexUrlExtractEngine indexUrlExtractEngine = new YahooSymbolIndexUrlExtractEngine();

            indexUrlExtractEngine.GetUrls();
        }

        private void button13_Click(object sender, EventArgs e)
        {
            YahooSymbolExtractor yahooSymbolExtractor = new YahooSymbolExtractor();

            IndexUrlDataAccess indexUrlDataAccess = new IndexUrlDataAccess();

            List<IndexUrl> indexUrls = indexUrlDataAccess.GetAllIndexUrls();

            foreach (IndexUrl indexUrl in indexUrls)
            {
                List<string> symbols = yahooSymbolExtractor.ExtractSymbolsFromUrl(indexUrl.Url);
            }
        }

        private void button14_Click(object sender, EventArgs e)
        {
            IBDSymbolsByCompositeRatingExtractor extractor = new IBDSymbolsByCompositeRatingExtractor();

            List<IBDRatings> ratingsList = new List<IBDRatings>();

            for (int i = 80; i <= 100; i++)
            {
                ratingsList.AddRange(extractor.GetByCompositeRating(i));
            }

            foreach (IBDRatings rating in ratingsList)
            {

            }
        }

        private void button15_Click(object sender, EventArgs e)
        {
            IBDSymbolsByCompositeRatingExtractor extractor = new IBDSymbolsByCompositeRatingExtractor();

            List<IBDRatings> ratingsList = extractor.GetByCompositeRating(99);
        }

        private void button16_Click(object sender, EventArgs e)
        {
            XmlDocument document = new XmlDocument();
            document.Load(@"C:\Users\simon\Desktop\test.xml");

            foreach (XmlNode node in document.ChildNodes)
            {
                foreach (XmlNode innerNode in node.ChildNodes)
                {
                    foreach (XmlNode dataNode in innerNode.ChildNodes)
                    {
                        foreach (XmlAttribute attribute in dataNode.Attributes)
                        {
                            string name = attribute.Name;
                            string value = attribute.Value;
                        }
                    }
                }
            }
        }

        private void button17_Click(object sender, EventArgs e)
        {
            IBDSymbolsByCompositeRatingExtractor extractor = new IBDSymbolsByCompositeRatingExtractor();

            List<IBDRatings> ratingsList = extractor.GetByCompositeRating(80);

            foreach (IBDRatings rating in ratingsList)
            {
                System.Diagnostics.Debug.WriteLine(rating);
            }
        }

        private void button18_Click(object sender, EventArgs e)
        {
            //int minRating = 80;
            //int maxRating = 99;
            //IBDSymbolsByCompositeRatingExtractor extractor = new IBDSymbolsByCompositeRatingExtractor();
            //List<IBDRatings> ratings = new List<IBDRatings>();
            //YahooHistoricPriceExtractor pricesExtractor = new YahooHistoricPriceExtractor();
            //SymbolDataAccess symbolDataAccess = new SymbolDataAccess();
            //StringBuilder stringBuilder = new StringBuilder();

            //stringBuilder.AppendLine("Getting IBD composites");

            ////loop and get IBD stocks within ratings range
            //for (int i = minRating; i <= maxRating; i++)
            //{
            //    System.Diagnostics.Debug.WriteLine(i);

            //    stringBuilder.AppendLine(i.ToString());

            //    ratings.AddRange(extractor.GetByCompositeRating(i));
            //}

            //stringBuilder.AppendLine("Getting symbols");

            ////get all existing symbols from database
            //List<Symbol> allSymbols = symbolDataAccess.GetAllSymbols();

            ////loop the ratings entries and find symbol dtabase match
            //foreach (IBDRatings rating in ratings)
            //{
            //    //find database entry for this stock
            //    string match = allSymbols.Find(symbol => symbol.Name == rating.Symbol);
                
            //    //does it exist?
            //    if (match != null)
            //    {
            //        //yes so set the reference
            //        rating.Symbol = match;
            //    }
            //    else
            //    {
            //        //no so insert into database
            //        //symbolDataAccess.InsertSymbol(rating.Symbol);
            //    }
            //}

            //List<Symbol> missingPrices = new List<Symbol>();
            //HistoricPricesExtract result = null;

            //DateTime fromDate = new DateTime(2009, 10, 31);
            //DateTime toDate = new DateTime(2010, 10, 31);

            //System.Diagnostics.Debug.WriteLine("Getting prices");
            //stringBuilder.AppendLine("Getting prices");
            //int counter = 0;

            ////then loop and download prices foreach
            //foreach (IBDRatings rating in ratings)
            //{
            //    System.Diagnostics.Debug.WriteLine(rating.Symbol.Name);
            //    counter++;
            //    System.Diagnostics.Debug.WriteLine(counter);                

            //    //download prices for symbol
            //    result = pricesExtractor.GetHistoricPrices(fromDate, toDate, rating.Symbol);

            //    //check result was ok
            //    if (result.HistoricPricesExtractResult == HistoricPricesExtractResult.SUCCESS)
            //    {
            //        rating.Symbol.Prices = result.DailyPrices;

            //        //
            //        rating.Symbol.GenerateWeeklyPrices();

            //        stringBuilder.AppendFormat("Sucess. Symbol: {0}, Number: {1}",
            //            rating.Symbol.Name, counter);
            //        stringBuilder.AppendLine();
            //    }
            //    else
            //    {
            //        missingPrices.Add(rating.Symbol);

            //        stringBuilder.AppendFormat("Failed. Symbol: {0}, Number: {1}, Reason: {2}",
            //            rating.Symbol.Name, counter, result.Message);
            //        stringBuilder.AppendLine();
            //    }
            //}

            //if (missingPrices.Count > 0)
            //{
            //    System.Diagnostics.Debug.WriteLine("Could not download prices for...");

            //    foreach (Symbol symbol in missingPrices)
            //    {
            //        System.Diagnostics.Debug.WriteLine(symbol.Name);
            //    }
            //}

            //ThreeWeekTightClosesChartPattern threeWeeksTight = new ThreeWeekTightClosesChartPattern();
            //WeeklyFlatBaseChartPattern weeklyFlatBase = new WeeklyFlatBaseChartPattern();
            //List<Symbol> threeWeeksTightSymbols = new List<Symbol>();
            //List<Symbol> weeklyFlatBaseSymbols = new List<Symbol>();
            //ChartPatternResult patternResult = null;

            //System.Diagnostics.Debug.WriteLine("Applying patterns");
            //stringBuilder.AppendLine("Applying patterns");

            //foreach (IBDRatings rating in ratings)
            //{
            //    patternResult = threeWeeksTight.Apply(rating.Symbol);

            //    if (patternResult.DoesFit)
            //    {
            //        System.Diagnostics.Debug.WriteLine(string.Format("Three Weeks Tight: {0}", rating.Symbol.Name));
            //        stringBuilder.AppendLine(string.Format("Three Weeks Tight: http://premium.investors.com/member/DgoGraphs/dgoGraphs.asp?cht=dgx&ibdMode=weekly&t={0}&bhcp=1", rating.Symbol.Name));
            //        threeWeeksTightSymbols.Add(rating.Symbol);
            //    }

            //    patternResult = weeklyFlatBase.Apply(rating.Symbol);

            //    if (patternResult.DoesFit)
            //    {
            //        System.Diagnostics.Debug.WriteLine(string.Format("Weekly flat base: {0}", rating.Symbol.Name));
            //        stringBuilder.AppendLine(string.Format("Weekly flat base: http://premium.investors.com/member/DgoGraphs/dgoGraphs.asp?cht=dgx&ibdMode=weekly&t={0}&bhcp=1", rating.Symbol.Name));
            //        weeklyFlatBaseSymbols.Add(rating.Symbol);
            //    }
            //}

            //System.Net.Mail.MailMessage m = new System.Net.Mail.MailMessage();
            //m.Body = stringBuilder.ToString();
            //m.To.Add("ssattin@gmail.com");
            //m.Subject = "Stock Results";
            //m.From = new System.Net.Mail.MailAddress("ssattin@gmail.com");
            //System.Net.Mail.SmtpClient c = new System.Net.Mail.SmtpClient("smtp.gmail.com", 587);
            //NetworkCredential myCreds = new NetworkCredential("ssattin@gmail.com", "bergkamp_10", "");
            //c.Credentials = myCreds;
            //c.EnableSsl = true;
            //c.Send(m);
        }

        private void button19_Click(object sender, EventArgs e)
        {
            /* 3 weeks tight */

            decimal weekOne = 100;
            decimal weekTwo = 101M;
            decimal weekThree = 100M;

            //find difference between first and second week
            decimal firstDifference = (Math.Abs(weekTwo - weekOne) / weekOne)*100;

            //then find the difference between second and third
            decimal secondDifference = (Math.Abs(weekThree - weekTwo) / weekTwo)*100;
            
            
        }

        private void button20_Click(object sender, EventArgs e)
        {
            System.Net.Mail.MailMessage m = new System.Net.Mail.MailMessage();
            m.Body = "test";
            m.To.Add("ssattin@gmail.com");
            m.Subject = "Stock Results";
            m.From = new System.Net.Mail.MailAddress("ssattin@gmail.com");
            System.Net.Mail.SmtpClient c = new System.Net.Mail.SmtpClient("smtp.gmail.com", 587);
            NetworkCredential myCreds = new NetworkCredential("ssattin@gmail.com", "bergkamp_10", "");
            c.Credentials = myCreds;
            c.EnableSsl = true;
            c.Send(m);
        }

        private void button21_Click(object sender, EventArgs e)
        {
            ////get prices
            //YahooHistoricPriceExtractor pricesExtractor = new YahooHistoricPriceExtractor();
            //string symbolName = "TDSC";
            //Symbol symbol = new Symbol() { Name = symbolName };
            //DateTime fromDate = new DateTime(2009, 10, 31);
            //DateTime toDate = new DateTime(2010, 10, 31);

            //HistoricPricesExtract result = pricesExtractor.GetHistoricPrices(
            //    fromDate, toDate, symbol);

            //symbol.Prices = result.DailyPrices;

            //symbol.GenerateWeeklyPrices();

            //ThreeWeekTightClosesChartPattern threeWeeksTight = new ThreeWeekTightClosesChartPattern();
            
            ////apply 3 weeks tight
            //threeWeeksTight.Apply(symbol);

            
        }

        private void _Stage2Button_Click(object sender, EventArgs e)
        {
            IBDDataAccess ratingsDataAccess = new IBDDataAccess();
            SymbolDataAccess symbolDataAccess = new SymbolDataAccess();

            System.Diagnostics.Debug.WriteLine("getting exiting ratings for " + DateTime.Now.Date);

            /* get ratings alreay in database for today */

            List<IBDRatings> existingRatings = ratingsDataAccess.GetAllIBDRatingsByDate(
                DateTime.Now.Date);   
         
            /* get up to date ratings from IBD */
            
            int minRating = 80;
            int maxRating = 99;
            List<IBDRatings> ratings = new List<IBDRatings>();
            IBDSymbolsByCompositeRatingExtractor extractor = new IBDSymbolsByCompositeRatingExtractor();

            System.Diagnostics.Debug.WriteLine("Getting current ratings from IBD");

            //loop the ratings
            for (int rating = minRating; rating <= maxRating; rating++)
            {
                System.Diagnostics.Debug.WriteLine(rating);

                //get IBD symbols with that rating
                ratings.AddRange(extractor.GetByCompositeRating(rating));
            }

            /* set symbol references and insert any new */

            List<Symbol> symbols = symbolDataAccess.GetAllSymbols();

            System.Diagnostics.Debug.WriteLine("Matching symbol references");

            foreach (IBDRatings rating in ratings)
            {
                //find matcing symbol
                Symbol match = symbols.Find(s => s.Name == rating.Symbol.Name);

                //no match?
                if (match == null)
                {
                    //insert new symbol
                    symbolDataAccess.InsertSymbol(rating.Symbol);
                }
                else
                {
                    //set correct reference
                    rating.Symbol = match;
                }
            }

            /* find any ratings not already in database */

            System.Diagnostics.Debug.WriteLine("Inserting new ratings");

            foreach (IBDRatings rating in ratings)
            {
                //find rating based on symbol
                IBDRatings match = existingRatings.Find(r => r.Symbol.SymbolId == rating.Symbol.SymbolId);

                if (match == null)
                {
                    //not in database so insert
                    ratingsDataAccess.InsertIBDRating(rating);
                }
            }

            System.Diagnostics.Debug.WriteLine("Inserting new prices");

            /* get prices foreach and insert any new ones */

            DailyPriceDataAccess pricesDataAccess = new DailyPriceDataAccess();
            IHistoricPricesExtractor pricesExtractor = new GoogleHistoricPriceExtractor();

            int ratingCount = 1;

            foreach (IBDRatings rating in ratings)
            {
                System.Diagnostics.Debug.WriteLine(ratingCount++);

                //get existing prices
                pricesDataAccess.GetAllDailyPricesBySymbolIdFromDate(rating.Symbol, 
                    DateTime.Now.AddYears(-1));

                //get prices from internet for past year
                HistoricPricesExtract result = pricesExtractor.GetHistoricPrices(rating.Symbol);

                //was it a success?
                if (result.HistoricPricesExtractResult == HistoricPricesExtractResult.SUCCESS)
                {
                    //yes so find any prices not exist
                    foreach (DailyPrice price in result.DailyPrices)
                    {
                        //find matching price for date
                        DailyPrice match = rating.Symbol.Prices.Find(p => p.PriceDate == price.PriceDate);

                        if (match == null)
                        {
                            price.SymbolId = rating.Symbol.SymbolId;

                            pricesDataAccess.InsertDailyPrice(price);
                        }
                    }
                }
            }

            System.Diagnostics.Debug.WriteLine("done");
        }

        private void _Stage3Button_Click(object sender, EventArgs e)
        {
            DateTime runDate = new DateTime(2010, 12, 05);

            SymbolListToTextFileWriter fileWriter = new SymbolListToTextFileWriter();

            /* get ratings from DB */

            IBDDataAccess ibdDataAccess = new IBDDataAccess();

            List<IBDRatings> ratings = ibdDataAccess.GetAllIBDRatingsByDate(runDate);

            /* set symbol references */

            SymbolDataAccess symbolDataAccess = new SymbolDataAccess();

            List<Symbol> symbols = symbolDataAccess.GetAllSymbols();

            System.Diagnostics.Debug.WriteLine("Matching symbol references");

            //loop the downloaded IBD rating Stocks
            foreach (IBDRatings rating in ratings)
            {
                //find matcing symbol
                Symbol match = symbols.Find(s => s.SymbolId == rating.Symbol.SymbolId);

                //no match?
                if (match == null)
                {
                    //this symbol doesnt exist in the database so insert
                    symbolDataAccess.InsertSymbol(rating.Symbol);
                }
                else
                {
                    //set correct reference
                    rating.Symbol = match;
                }
            }

            /* fill prices for each */

            DailyPriceDataAccess pricesDataAccess = new DailyPriceDataAccess();

            foreach (IBDRatings rating in ratings)
            {
                pricesDataAccess.GetAllDailyPricesBySymbolIdFromDate(
                    rating.Symbol, runDate.AddYears(-1));

                rating.Symbol.GenerateWeeklyPrices();
            }

            /* run through weekly flat base */

            ChartPatternResult patternResult = null;

            WeeklyFlatBaseChartPattern weeklyFlatBase = new WeeklyFlatBaseChartPattern();

            List<string> flatBases = new List<string>();

            foreach (IBDRatings rating in ratings)
            {
                 patternResult = weeklyFlatBase.Apply(rating.Symbol);

                 if (patternResult.DoesFit)
                 {
                     flatBases.Add(rating.Symbol.Name);
                 }
            }

            fileWriter.Write(flatBases, "Flatbase.txt");

            /* run through cupWithHandleBases */

            WeeklyCupWithHandleBaseChartPattern cupWithHandle = new WeeklyCupWithHandleBaseChartPattern();

            List<string> cupWithHandleBases = new List<string>();

            foreach (IBDRatings rating in ratings)
            {
                patternResult = cupWithHandle.Apply(rating.Symbol);

                if (patternResult.DoesFit)
                {
                    cupWithHandleBases.Add(rating.Symbol.Name);
                }
            }

            fileWriter.Write(cupWithHandleBases, "CupBase.txt");

            /* run through cupWithHandleBases */

            ThreeWeekTightClosesChartPattern threeWeeksTight = new ThreeWeekTightClosesChartPattern();

            List<string> threeWeeksTightBases = new List<string>();

            foreach (IBDRatings rating in ratings)
            {
                patternResult = threeWeeksTight.Apply(rating.Symbol);

                if (patternResult.DoesFit)
                {
                    threeWeeksTightBases.Add(rating.Symbol.Name);
                }
            }

            fileWriter.Write(threeWeeksTightBases, "ThreeWeeksTight.txt");

            /* run through high tight flag */

            HighTightFlagPattern highTightFlagPattern = new HighTightFlagPattern();

            List<string> highTightFlags = new List<string>();

            foreach (IBDRatings rating in ratings)
            {
                patternResult = highTightFlagPattern.Apply(rating.Symbol);

                if (patternResult.DoesFit)
                {
                    highTightFlags.Add(rating.Symbol.Name);
                }
            }

            fileWriter.Write(highTightFlags, "HighTightFlags.txt");

            /* list the bases */

            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.AppendLine("<table>");
            stringBuilder.AppendLine("<tr><td>Flat bases</td></tr>");

            stringBuilder.AppendFormat("<tr>");

            foreach (string flatBase in flatBases)
            {
                stringBuilder.AppendFormat("<tr>");
                stringBuilder.AppendFormat("<td>{0}</td>",flatBase);
                stringBuilder.AppendFormat("<td><a href='http://chart.finance.yahoo.com/z?s={0}&t=6m&q=c&l=on&z=l&p=m50,m200,v&a=ss,r14&lang=en-US&region=US' target='_top'>daily yahoo</a></td>", flatBase);
                stringBuilder.AppendFormat("<td><a href='http://chart.finance.yahoo.com/z?s={0}&t=2y&q=c&l=on&z=l&p=m50,m200,v&a=ss,r14&lang=en-US&region=US' target='_top'>weekly yahoo</a></td>", flatBase);
                stringBuilder.AppendFormat("<td><a href='http://premium.investors.com/member/DgoGraphs/dgoGraphs.asp?cht=dgx&ibdMode=weekly&t={0}&bhcp=1' target='_top'>IBD</a></td>", flatBase);
                stringBuilder.AppendFormat("</tr>");
            }

            stringBuilder.AppendFormat("</tr>");

            stringBuilder.AppendLine();

            stringBuilder.AppendLine("<tr><td>Cup with handle bases</td></tr>");

            stringBuilder.AppendFormat("<tr>");

            foreach (string cupWithHandleBase in cupWithHandleBases)
            {
                stringBuilder.AppendFormat("<tr>");
                stringBuilder.AppendFormat("<td>{0}</td>", cupWithHandleBase);
                stringBuilder.AppendFormat("<td><a href='http://chart.finance.yahoo.com/z?s={0}&t=6m&q=c&l=on&z=l&p=m50,m200,v&a=ss,r14&lang=en-US&region=US' target='_top'>daily yahoo</a></td>", cupWithHandleBase);
                stringBuilder.AppendFormat("<td><a href='http://chart.finance.yahoo.com/z?s={0}&t=2y&q=c&l=on&z=l&p=m50,m200,v&a=ss,r14&lang=en-US&region=US' target='_top'>weekly yahoo</a></td>", cupWithHandleBase);
                stringBuilder.AppendFormat("<td><a href='http://premium.investors.com/member/DgoGraphs/dgoGraphs.asp?cht=dgx&ibdMode=weekly&t={0}&bhcp=1' target='_top'>IBD</a></td>", cupWithHandleBase);
                stringBuilder.AppendFormat("</tr>");
            }

            stringBuilder.AppendFormat("</tr>");

            stringBuilder.AppendLine();

            stringBuilder.AppendLine("<tr><td>3 weeks tight bases</td></tr>");

            stringBuilder.AppendFormat("<tr>");

            foreach (string threeWeeksTightBase in threeWeeksTightBases)
            {
                stringBuilder.AppendFormat("<tr>");
                stringBuilder.AppendFormat("<td>{0}</td>", threeWeeksTightBase);
                stringBuilder.AppendFormat("<td><a href='http://chart.finance.yahoo.com/z?s={0}&t=6m&q=c&l=on&z=l&p=m50,m200,v&a=ss,r14&lang=en-US&region=US' target='_top'>daily yahoo</a></td>", threeWeeksTightBase);
                stringBuilder.AppendFormat("<td><a href='http://chart.finance.yahoo.com/z?s={0}&t=2y&q=c&l=on&z=l&p=m50,m200,v&a=ss,r14&lang=en-US&region=US' target='_top'>weekly yahoo</a></td>", threeWeeksTightBase);
                stringBuilder.AppendFormat("<td><a href='http://premium.investors.com/member/DgoGraphs/dgoGraphs.asp?cht=dgx&ibdMode=weekly&t={0}&bhcp=1' target='_top'>IBD</a></td>", threeWeeksTightBase);                
                stringBuilder.AppendFormat("</tr>");
            }

            stringBuilder.AppendLine("<tr><td>high tight flag</td></tr>");

            stringBuilder.AppendFormat("<tr>");

            foreach (string highTightFlag in highTightFlags)
            {
                stringBuilder.AppendFormat("<tr>");
                stringBuilder.AppendFormat("<td>{0}</td>", highTightFlag);
                stringBuilder.AppendFormat("<td><a href='http://chart.finance.yahoo.com/z?s={0}&t=6m&q=c&l=on&z=l&p=m50,m200,v&a=ss,r14&lang=en-US&region=US' target='_top'>daily yahoo</a></td>", highTightFlag);
                stringBuilder.AppendFormat("<td><a href='http://chart.finance.yahoo.com/z?s={0}&t=2y&q=c&l=on&z=l&p=m50,m200,v&a=ss,r14&lang=en-US&region=US' target='_top'>weekly yahoo</a></td>", highTightFlag);
                stringBuilder.AppendFormat("<td><a href='http://premium.investors.com/member/DgoGraphs/dgoGraphs.asp?cht=dgx&ibdMode=weekly&t={0}&bhcp=1' target='_top'>IBD</a></td>", highTightFlag);
                stringBuilder.AppendFormat("</tr>");
            }

            stringBuilder.AppendFormat("</tr></table>");

            System.Net.Mail.MailMessage m = new System.Net.Mail.MailMessage();
            m.Body = stringBuilder.ToString();
            m.To.Add("ssattin@gmail.com");
            m.Subject = "Stock Results";
            m.IsBodyHtml = true;
            m.From = new System.Net.Mail.MailAddress("ssattin@gmail.com");
            System.Net.Mail.SmtpClient c = new System.Net.Mail.SmtpClient("smtp.gmail.com", 587);
            NetworkCredential myCreds = new NetworkCredential("ssattin@gmail.com", "bergkamp_10", "");
            c.Credentials = myCreds;
            c.EnableSsl = true;
            c.Send(m);
        }

        private void _TestAFOPCup_Click(object sender, EventArgs e)
        {
            /* tests the cup with handle against AFOP */

            DateTime fromDate = new DateTime(2010, 6, 8);
            DateTime toDate = new DateTime(2010, 10, 15);
            Symbol symbol = new Symbol(){ Name = "AFOP"};

            IHistoricPricesExtractor pricesExtractor = new GoogleHistoricPriceExtractor();

            HistoricPricesExtract pricesResult = pricesExtractor.GetHistoricPrices(symbol);

            symbol.Prices = pricesResult.DailyPrices;
            
            symbol.GenerateWeeklyPrices();

            WeeklyCupWithHandleBaseChartPattern cupWithHandle = new WeeklyCupWithHandleBaseChartPattern();

            ChartPatternResult patternResult = cupWithHandle.Apply(symbol);
        }

        private void _AdjustPricesTest_Click(object sender, EventArgs e)
        {
            /* get all symbols */

            SymbolDataAccess symbolDataAccess = new SymbolDataAccess();
            DailyPriceDataAccess dailyPriceDataAccess = new DailyPriceDataAccess();

            List<Symbol> symbols = symbolDataAccess.GetAllSymbols();

            foreach (Symbol symbol in symbols)
            {
                //get prices
                dailyPriceDataAccess.GetAllDailyPricesBySymbolIdFromDate(
                    symbol, DateTime.Now.AddYears(-1));
            }
        }

        private void button22_Click(object sender, EventArgs e)
        {
            /* google price extractor */

            IHistoricPricesExtractor pricesExtractor = new GoogleHistoricPriceExtractor();

            Symbol symbol = new Symbol();
            symbol.Name = "CLF";
            symbol.SymbolId = 123;

            //get prices from last year
            HistoricPricesExtract result = pricesExtractor.GetHistoricPrices(symbol);

            symbol.Prices = result.DailyPrices;

            symbol.GenerateWeeklyPrices();
        }

        /// <summary>
        /// Gets all stocks in IBDs top 5% that are in 3 weeks tight
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _ThreeWeeksTight9995Button_Click(object sender, EventArgs e)
        {
            #region Get Top 5% IBD stocks list


            #endregion
        }

        private void _UniqueSymbolsButton_Click(object sender, EventArgs e)
        {
            UniqueSymbolsListForm symbolsListForm = new UniqueSymbolsListForm();

            symbolsListForm.ShowDialog();
        }

        private void _FlatBaseFinderButton_Click(object sender, EventArgs e)
        {
            FlatBaseFinderForm flatBaseFinderForm = new FlatBaseFinderForm();

            flatBaseFinderForm.ShowDialog();
        }

        private void _EIBDSymbolListGenerator_Click(object sender, EventArgs e)
        {
            EIBDSymbolListGeneratorForm eibdSymbolListGeneratorForm = new EIBDSymbolListGeneratorForm();

            eibdSymbolListGeneratorForm.ShowDialog();
        }

        private void _SymbolListByTableButton_Click(object sender, EventArgs e)
        {
            EIBDSymbolListGeneratorByTableForm form = new EIBDSymbolListGeneratorByTableForm();

            form.ShowDialog();
        }

        private void _SimpleMovingAverageTestButton_Click(object sender, EventArgs e)
        {
            /* get all prices for AAPL - 3711 */

            //Symbol appleSymbol = new Symbol()
            //{
            //    Name = "AAPL",
            //    SymbolId = 3711
            //};

            SymbolDataAccess symbolDataAccess = new SymbolDataAccess();

            List<Symbol> symbols = symbolDataAccess.GetListOfSymbolsThatHavePrices();

            DailyPriceDataAccess dailyPriceDataAccess = new DailyPriceDataAccess();

            decimal accountTotal = 50000;
            decimal riskAmount = 1;
            decimal commission = 2;
            decimal skid = 0.05M;
            List<TestTrade> winningTrades = new List<TestTrade>();
            List<TestTrade> losingTrades = new List<TestTrade>();

            foreach (Symbol symbol in symbols)
            {
                #region Get Prices

                dailyPriceDataAccess.GetAllDailyPricesBySymbolId(symbol);

                symbol.GenerateWeeklyPrices();

                #endregion

                #region Get Moving Averages

                /* list all prices and calculte the moving averages for each date */

                SimpleMovingAverageCalculator simpleMovingAverage = new SimpleMovingAverageCalculator();

                DateTime priceDate = DateTime.MinValue;
                decimal slowMovingAverage = 0;
                decimal fastMovingAverage = 0;

                //loop the prices
                foreach (DailyPrice price in symbol.Prices)
                {
                    priceDate = price.PriceDate;

                    //calculate the slow MA
                    slowMovingAverage = simpleMovingAverage.Calculate(symbol, 50, priceDate);

                    fastMovingAverage = simpleMovingAverage.Calculate(symbol, 10, priceDate);

                    //set the indicators and moving averages
                    if (price.Indicators == null)
                    {
                        price.Indicators = new DailyPriceIndicator();
                    }

                    price.Indicators.MA50 = slowMovingAverage;

                    price.Indicators.MA10 = fastMovingAverage;
                }

                #endregion

                //reverse the list
                symbol.Prices.Reverse();

                //symbol.Prices.ForEach(i => Debug.WriteLine(string.Format("Date: {0}. Slow MA: {1}. Fast MA: {2}",
                //    i.PriceDate, i.Indicators.MA50, i.Indicators.MA10)));

                #region Perform test

                bool crossOverFlag = false;

                List<TestTrade> testTrades = new List<TestTrade>();

                TestTrade testTrade = null;

                foreach (DailyPrice price in symbol.Prices)
                {
                    if (price.Indicators.MA10 > 0 && price.Indicators.MA50 > 0)
                    {
                        //fast higher than slow
                        if (price.Indicators.MA10 > price.Indicators.MA50)
                        {
                            //cut position at 8%
                            if (testTrade != null)
                            {
                                if (((price.Close - testTrade.BuyPrice) / testTrade.BuyPrice) < -0.08M)
                                {
                                    //close the position
                                    testTrade.SellDate = price.PriceDate;

                                    testTrade.SellPrice = price.Close;

                                    testTrades.Add(testTrade);

                                    //reset test trade
                                    testTrade = null;
                                }
                            }

                            //crossing up
                            if (!crossOverFlag)
                            {
                                crossOverFlag = true;

                                //open a position
                                testTrade = new TestTrade();

                                testTrade.BuyDate = price.PriceDate;

                                testTrade.BuyPrice = price.Close;
                            }
                        }
                        else
                        {
                            //crossing down
                            if (crossOverFlag && testTrade != null)
                            {
                                crossOverFlag = false;

                                //close the position
                                testTrade.SellDate = price.PriceDate;

                                testTrade.SellPrice = price.Close;

                                testTrades.Add(testTrade);

                                //reset test trade
                                testTrade = null;
                            }
                        }
                    }

                    //Debug.WriteLine(string.Format("Date: {0}. Flag: {1}. Slow: {2}. Fast: {3}", price.PriceDate,
                    //    crossOverFlag, price.Indicators.MA50, price.Indicators.MA10));
                }

                if (testTrade != null)
                {
                    testTrades.Add(testTrade);

                    testTrade.SellPrice = symbol.Prices[symbol.Prices.Count - 1].Close;

                    testTrade.SellDate = symbol.Prices[symbol.Prices.Count - 1].PriceDate;
                }

                //testTrades.ForEach(i => Debug.WriteLine(string.Format("Result: {0}. Length: {1}",
                //    i.GetTradeResult(), i.GetLengthInDays())));

                #endregion

                decimal position = 0;

                foreach (TestTrade trade in testTrades)
                {
                    //position is 1% of account
                    position = Math.Floor((accountTotal / 100) * riskAmount);

                    accountTotal -= position;

                    position = position + (position * (trade.GetTradeResult(skid) / 100));                    

                    accountTotal += position;

                    accountTotal -= commission;

                    Debug.WriteLine(accountTotal);

                    if (trade.BuyPrice < trade.SellPrice)
                    {
                        winningTrades.Add(trade);
                    }
                    else
                    {
                        losingTrades.Add(trade);
                    }
                }

                //Debug.WriteLine(string.Format("Symbol: {0}. Account: {1}", symbol.Name, account));
            }

            Debug.WriteLine(string.Format("Account Total: {0}", accountTotal));

            decimal average = 0;

            foreach (TestTrade testTrade in winningTrades)
            {
                average += testTrade.GetTradeResult(skid);
            }

            average = average / winningTrades.Count;

            Debug.WriteLine("Average winner: " + average);

            average = 0;

            foreach (TestTrade testTrade in losingTrades)
            {
                average += testTrade.GetTradeResult(skid);
            }

            average = average / winningTrades.Count;

            Debug.WriteLine("Average loser: " + average);
        }

        private void _AverageTrueRangeButton_Click(object sender, EventArgs e)
        {
            AverageTrueRangeCalculator calculator = new AverageTrueRangeCalculator();

            SymbolDataAccess symbolDataAccess = new SymbolDataAccess();

            DailyPriceDataAccess pricesDataAccess = new DailyPriceDataAccess();

            Symbol amazonSymbol = new Symbol(){ SymbolId = 2521, Name = "AMZN"};

            pricesDataAccess.GetAllDailyPricesBySymbolId(amazonSymbol);

            amazonSymbol.GenerateWeeklyPrices();

            DateTime priceDate = DateTime.MinValue;

            //loop the prices
            foreach (DailyPrice price in amazonSymbol.Prices)
            {
                priceDate = price.PriceDate;

                if (price.Indicators == null)
                {
                    price.Indicators = new DailyPriceIndicator();
                }

                //calculate the 14 day average true range
                price.Indicators.ATR14 = calculator.Calculate(amazonSymbol, 14, priceDate);

                Debug.WriteLine(string.Format("{0} = {1}", priceDate.ToString("dd/MM/yy"), price.Indicators.ATR14));
            }            
        }

        private void _FindAllTimeHighButton_Click(object sender, EventArgs e)
        {
            int successCount = 0;
            
            //1. load symbols
            //ISymbolExtractor symbolsExtractor = new EODDataSymbolListExtractor();

            //IHistoricPricesExtractor priceExtractor = new YahooHistoricPriceExtractor();

            //List<string> nasdaqSymbolList = symbolsExtractor.ExtractSymbolsFromUrl(@"C:\Data\SymbolList\NYSE.txt");

            //List<Symbol> symbols = new List<Symbol>();

            //Debug.WriteLine("Creating Symbols list");

            ////create symbols list
            //nasdaqSymbolList.ForEach(s => { symbols.Add(new Symbol() { Name = s }); });

            //Debug.WriteLine(string.Format("Getting price history. {0}", DateTime.Now));

            ////the get price history for symbols
            //Parallel.ForEach(symbols, symbol => 
            //{
            //    //get price history
            //    HistoricPricesExtract result = priceExtractor.GetHistoricPrices(
            //        DateTime.Today.AddYears(-20), DateTime.Today, symbol);

            //    //set the prices
            //    symbol.Prices = result.DailyPrices;
            //});

            ////see how many were successful
            //symbols.ForEach(symbol => { if (symbol.Prices != null && symbol.Prices.Count > 0) successCount++; });

            //Debug.WriteLine(string.Format("{0} out of {1}. {2}", successCount, symbols.Count, DateTime.Now));

            //Debug.WriteLine(string.Format("Getting price history. {0}", DateTime.Now));

            ////get prices again
            //symbols.ForEach(symbol => priceExtractor.GetHistoricPrices(DateTime.Today.AddYears(-20), DateTime.Today, symbol));

            //successCount = 0;

            ////see how many were successful
            //symbols.ForEach(symbol => { if (symbol.Prices != null && symbol.Prices.Count > 0) successCount++; });

            //Debug.WriteLine(string.Format("{0} out of {1}. {2}", successCount, symbols.Count, DateTime.Now));

            //2. loop symbols

            //3. load all price history for symbol

            //4. find historic close

            //5. is latest close higher than highest close

            //6. calculate the ATR

            //7. calculate ATR multiple            
            
            /* loop symbols */

           
            
            /* load historic prices */
        }

        private void _EODDataSymbolsButton_Click(object sender, EventArgs e)
        {
            //ISymbolExtractor symbolsExtractor = new EODDataSymbolListExtractor();

            //IHistoricPricesExtractor priceExtractor = new YahooHistoricPriceExtractor();

            //List<string> nasdaqSymbolList = symbolsExtractor.ExtractSymbolsFromUrl(@"C:\Data\SymbolList\NYSE.txt");

            //List<Symbol> symbols = new List<Symbol>();

            //nasdaqSymbolList.ForEach(s => symbols.Add(new Symbol(){ Name = s}));

            //symbols.ForEach(s => priceExtractor.GetHistoricPrices(DateTime.Today.AddYears(-20), DateTime.Today, s));

            //foreach (var symbol in symbols)
            //{

            //}
        }

        private void _FillLatestSymbolsButton_Click(object sender, EventArgs e)
        {
            //1. truncate the symbols list
            //SymbolDataAccess symbolDataAccess = new SymbolDataAccess();

            //symbolDataAccess.TruncateSymbolTable();

            ////2. download the files

            ////3. extract the symbols
            //ISymbolExtractor symbolsExtractor = new EODDataSymbolListExtractor();

            //List<string> nyseSymbolList = symbolsExtractor.ExtractSymbolsFromUrl(@"C:\Data\StockFinder\trunk\SymbolList\NYSE.txt");

            //List<string> nasdaqSymbolList = symbolsExtractor.ExtractSymbolsFromUrl(@"C:\Data\StockFinder\trunk\SymbolList\NASDAQ.txt");

            //List<Symbol> symbols = new List<Symbol>();

            //nyseSymbolList.ForEach(symbol => symbols.Add(new Symbol(){ Name = symbol}));

            //nasdaqSymbolList.ForEach(symbol => symbols.Add(new Symbol(){ Name = symbol}));

            ////4. insert into database
            //symbolDataAccess.InsertSymbols(symbols);
        }

        private void _DownloadPriceHistoryButton_Click(object sender, EventArgs e)
        {
            _Log.DebugFormat("Download prices for symbols");

            SymbolDataAccess symbolDataAccess = new SymbolDataAccess();

            int MAX_ATTEMPTS = 10;

            //1. get symbols from database
            List<Symbol> symbols = symbolDataAccess.GetAllSymbols();

            _Log.DebugFormat("{0} symbols", symbols.Count);

            IEnumerable<Symbol> symbolsToDownload = symbols;

            //2. loop each and extract prices - try 10 times
            for (int attempts = 1; attempts <= MAX_ATTEMPTS; attempts++)
            {
                _Log.DebugFormat("Download batch #{0}", attempts);

                DownloadPricesForSymbols(symbolsToDownload.Where(symbol => !symbol.HasLoadedPrices));
            }
           
            //3. print list of those that didnt download

            Debug.WriteLine("Following symbols couldnt not be downloaded:");

            symbols.ForEach(symbol =>
                {
                    if (symbol.Prices == null) Debug.WriteLine(symbol);
                });
            
            //4. insert downloaded prices
            //DailyPriceDataAccess dailyPriceDataAccess = new DailyPriceDataAccess();

            //symbols.ForEach(symbol =>
            //{
            //    //check symbol has prices
            //    if (symbol.Prices != null && symbol.Prices.Count > 0)
            //    {
            //        symbol.Prices.ForEach(price =>
            //        {
            //            //set symbolid reference
            //            price.SymbolId = symbol.SymbolId;

            //            dailyPriceDataAccess.InsertDailyPrice(price);
            //        });
            //    }
            //});
        }

        private void DownloadPricesForSymbols(IEnumerable<Symbol> symbols)
        {
            //IHistoricPricesExtractor priceExtractor = new TestHistoricPricesExtractor();
            IHistoricPricesExtractor priceExtractor = new YahooHistoricPriceExtractor();
            DailyPriceDataAccess dailyPriceDataAccess = new DailyPriceDataAccess();

            _Log.DebugFormat("Attempting to download {0} symbols prices", symbols.Count());

            int counter = 0;

            //Parallel.ForEach(symbols, symbol =>
            foreach (var symbol in symbols)
            {
                _Log.DebugFormat("Downloading prices for {0} ({1})", symbol.Name, symbol.SymbolId);

                //get price history - last 20 years
                HistoricPricesExtract result = priceExtractor.GetHistoricPrices(
                    DateTime.Today.AddYears(-20), DateTime.Today, symbol);

                //set the prices
                //symbol.Prices = result.DailyPrices;

                if (result.HistoricPricesExtractResult == HistoricPricesExtractResult.SUCCESS)
                {
                    _Log.DebugFormat("***** Downloaded {0} prices for {1} *****", result.DailyPrices.Count, symbol.Name);

                    //inserting prices
                    //dailyPriceDataAccess.InsertDailyPrices(result.DailyPrices);
                    symbol.Prices = result.DailyPrices;

                    symbol.HasLoadedPrices = true;
                }
                else
                {
                    _Log.DebugFormat("Downloaded failed for {0} ({1})", symbol.Name, symbol.SymbolId);
                }

                result = null;
                //});
            }
        }

        private void _TestLogButton_Click(object sender, EventArgs e)
        {
            _Log.DebugFormat("Test123");
        }

        private void _TestHistoricPricesDummyBut_Click(object sender, EventArgs e)
        {
            SymbolDataAccess symbolDataAccess = new SymbolDataAccess();

            DailyPriceDataAccess priceDataAccess = new DailyPriceDataAccess();

            IHistoricPricesExtractor extractor = new TestHistoricPricesExtractor();

            List<Symbol> symbols = symbolDataAccess.GetAllSymbols();

            HistoricPricesExtract result = null;

            foreach (var symbol in symbols)
            {
                //fill test prices
                result = extractor.GetHistoricPrices(symbol);

                foreach (var price in result.DailyPrices)
                {
                    priceDataAccess.InsertDailyPrice(price);
                }
            }
        }

        private void _DownloadAndTest500SymbolsButton_Click(object sender, EventArgs e)
        {
            SymbolDataAccess symbolDataAccess = new SymbolDataAccess();

            IHistoricPricesExtractor priceExtractor = new YahooHistoricPriceExtractor();

            List<Symbol> symbols = symbolDataAccess.GetAllSymbols();

            IEnumerable<Symbol> symbolsList = symbols.Take(500);

            HistoricPricesExtract extract = null;

            foreach (var symbol in symbolsList)
            {
                _Log.DebugFormat("Downloading prices for {0} ({1})", symbol.Name, symbol.SymbolId);

                extract = priceExtractor.GetHistoricPrices(DateTime.Today.AddYears(-20), DateTime.Today, symbol);

                if (extract.HistoricPricesExtractResult == HistoricPricesExtractResult.SUCCESS)
                {
                    _Log.DebugFormat("***** Downloaded {0} prices for {1} *****", extract.DailyPrices.Count, symbol.Name);

                    symbol.Prices = extract.DailyPrices;
                }
                else
                {
                    _Log.DebugFormat("Downloaded failed for {0} ({1})", symbol.Name, symbol.SymbolId);
                }
            }
        }

        private void _AllTimeHighTestButton_Click(object sender, EventArgs e)
        {
            //AES - 53
            List<Symbol> symbols = _SymbolDataAccess.GetAllSymbols();

            List<Symbol> allTimeHighSymbols = new List<Symbol>();
            List<Symbol> breakOutRangeSymbols = new List<Symbol>();
            List<Symbol> justBrokenOutSymbols = new List<Symbol>();
            HistoricPricesExtract result = null;
            Symbol symbol = null;
            IOrderedEnumerable<DailyPrice> orderedPrices = null;

            _Log.DebugFormat("Looping symbols...");

            for (int index = 0; index < symbols.Count; index++)
            {
                symbol = symbols[index];

                _Log.DebugFormat("Downloading: {0} ({1})", symbol.Name, symbol.SymbolId);             

                result = _YahooPricesExtractor.GetHistoricPrices(DateTime.Today.AddYears(-20), DateTime.Today, symbol);

                if (result.HistoricPricesExtractResult == HistoricPricesExtractResult.SUCCESS)
                {
                    _Log.DebugFormat("**** Downloaded {0} prices ****", result.DailyPrices.Count);

                    try
                    {
                        //insert prices
                        _DailyPriceDataAccess.InsertDailyPrices(result.DailyPrices);
                    }
                    catch (Exception exception)
                    {
                        _Log.ErrorFormat("An unexpected error occurred inserting prices", exception.ToString());                                                
                    }                    

                    //order prices
                    orderedPrices = result.DailyPrices.OrderByDescending(price => price.PriceDate);

                    //is symbol at all time high?
                    if (PriceAnalyser.IsAtAllTimeHigh(orderedPrices))
                    {
                        _Log.DebugFormat("!!!Symbol at all time high!!!!");
                        allTimeHighSymbols.Add(symbol);
                    }

                    if (PriceAnalyser.IsCloseToAllTimeHigh(orderedPrices, 10, 30))
                    {
                        _Log.DebugFormat("@@@@ Symbol at breakout range @@@@");
                        breakOutRangeSymbols.Add(symbol);
                    }

                    if (PriceAnalyser.HasJustBrokenOut(orderedPrices, 30))
                    {
                        _Log.DebugFormat("^^^^ Symbol has just broken out ^^^^");
                        justBrokenOutSymbols.Add(symbol);
                    }
                }
                else
                {
                    _Log.DebugFormat("Download failed: {0}", result.Message);
                }
            }

            _Log.DebugFormat("Following symbols are at all time high");

            allTimeHighSymbols.ForEach(s => _Log.DebugFormat("{0} ({1})", s.Name, s.SymbolId));

            _Log.DebugFormat("Following symbols are at breakout range");

            breakOutRangeSymbols.ForEach(s => _Log.DebugFormat("{0} ({1})", s.Name, s.SymbolId));

            _Log.DebugFormat("Following symbols have just broken out");

            justBrokenOutSymbols.ForEach(s => _Log.DebugFormat("{0} ({1})", s.Name, s.SymbolId));
        }

        private void _PriceAnalyserRunButton_Click(object sender, EventArgs e)
        {
            //1 load symbols
            List<Symbol> symbols = _SymbolDataAccess.GetAllSymbols();

            _Log.DebugFormat("Looping {0} symbols", symbols.Count);

            List<DailyPrice> prices = null;
            List<Symbol> withRangeSymbols = new List<Symbol>();

            //2 load prices for symbol
            foreach (var symbol in symbols)
            {
                _Log.DebugFormat("Analysing {0} ({1})", symbol.Name, symbol.SymbolId);

                //load the prices
                prices = _DailyPriceDataAccess.GetAllPricesBySymbolId(symbol.SymbolId);

                _Log.DebugFormat("Loaded {0} prices", prices.Count);

                if (prices.Count > 0)
                {
                    _Log.DebugFormat("Analysing IsWithinBreakoutRange. Percentage: 5. Base length: 30");

                    if (PriceAnalyser.IsWithinBreakoutRange(prices.OrderByDescending(price => price.PriceDate), 5, 30))
                    {
                        withRangeSymbols.Add(symbol);

                        _Log.DebugFormat("***** IS WITHIN BREAKOUT RANGE *****");
                    }
                }                
            }

            _Log.DebugFormat("Following {0} symbols are within breakout range:", withRangeSymbols.Count);

            withRangeSymbols.ForEach(symbol => _Log.DebugFormat("{0} ({1})", symbol.Name, symbol.SymbolId));

            _Log.DebugFormat("Filtering out those below $15");
            
            //filter those below $15
            IEnumerable<Symbol> filteredSymbols = withRangeSymbols.Where(symbol => symbol.Prices[0].AdjustedClose >= 15);
            
            _Log.DebugFormat("Completed");
        }

        private void _GMCRTestButton_Click(object sender, EventArgs e)
        {
            //get GMCR prices
            List<DailyPrice> prices = _DailyPriceDataAccess.GetAllPricesBySymbolId(3779); 
  
            DateTime filterDate = new DateTime(2011, 2, 2);

            //filter by date
            IEnumerable<DailyPrice> filteredPrices = prices.Where(price => price.PriceDate <= filterDate);

            //run price analyser
            if (PriceAnalyser.IsWithinBreakoutRange(filteredPrices.OrderByDescending(price => price.PriceDate), 5, 30))
            {
                _Log.DebugFormat("***** IS WITHIN BREAKOUT RANGE *****");
            }
        }

        private void _HasJustBrokenOutButton_Click(object sender, EventArgs e)
        {
            //1 load symbols
            List<Symbol> symbols = _SymbolDataAccess.GetAllSymbols();

            _Log.DebugFormat("Looping {0} symbols", symbols.Count);

            List<DailyPrice> prices = null;
            List<Symbol> withRangeSymbols = new List<Symbol>();

            //2 load prices for symbol
            foreach (var symbol in symbols)
            {
                _Log.DebugFormat("Analysing {0} ({1})", symbol.Name, symbol.SymbolId);

                //load the prices
                prices = _DailyPriceDataAccess.GetAllPricesBySymbolId(symbol.SymbolId);

                _Log.DebugFormat("Loaded {0} prices", prices.Count);

                if (prices.Count > 0)
                {
                    _Log.DebugFormat("Analysing HasJustBrokenOut. Base length: 30");

                    if (PriceAnalyser.HasJustBrokenOut(prices.OrderByDescending(price => price.PriceDate), 30))
                    {
                        withRangeSymbols.Add(symbol);

                        _Log.DebugFormat("***** HAS JUST BROKEN OUT *****");
                    }
                }
            }

            _Log.DebugFormat("Following {0} symbols are within breakout range:", withRangeSymbols.Count);

            withRangeSymbols.ForEach(symbol => _Log.DebugFormat("{0} ({1})", symbol.Name, symbol.SymbolId));

            _Log.DebugFormat("Filtering out those below $15");

            //filter those below $15
            IEnumerable<Symbol> filteredSymbols = withRangeSymbols.Where(symbol => symbol.Prices[0].AdjustedClose >= 15);

            _Log.DebugFormat("Completed");
        }

        private void _SINATestButton_Click(object sender, EventArgs e)
        {
            //4986 SINA

            //16 sept 2010 - breakout date
            DateTime breakOutDate = new DateTime(2010, 11, 4);

            List<DailyPrice> prices = _DailyPriceDataAccess.GetAllPricesBySymbolId(4986);

            IEnumerable<DailyPrice> filteredPrices = prices.Where(price => price.PriceDate <= breakOutDate);

            if (PriceAnalyser.HasJustBrokenOut(filteredPrices.OrderByDescending(price => price.PriceDate), 30))
            {
                //has broken out
            }
        }

        private void _RSITestButton_Click(object sender, EventArgs e)
        {
            RelativeStrengthIndicatorCalculator rsiCalculator = new RelativeStrengthIndicatorCalculator();
            GeneralDataAccess _GeneralDataAccess = new GeneralDataAccess();
            SymbolDataAccess _SymbolDataAccess = new SymbolDataAccess();
            DailyPriceDataAccess _DailyPriceDataAccess = new DailyPriceDataAccess();
            ResultsDataAccess _ResultsDataAccess = new ResultsDataAccess();
            IHistoricPricesExtractor _YahooricesExtractor = new YahooHistoricPriceExtractor();
            IBDDataAccess _IBDDataAccess = new IBDDataAccess();

            //2. download top 25% IBD symbols
            _Log.DebugFormat("Looping rating indexes..");

            IBDSymbolsByCompositeRatingExtractor ibdSymbolsByCompositeRatingExtractor = new IBDSymbolsByCompositeRatingExtractor();

            List<IBDRatings> ratings = new List<IBDRatings>();

            ratings.AddRange(ibdSymbolsByCompositeRatingExtractor.GetByCompositeRating(99));

            HistoricPricesExtract result = null;

            foreach (IBDRatings rating in ratings)
            {
                result = _YahooricesExtractor.GetHistoricPrices(DateTime.Now.AddYears(-15), DateTime.Today, rating.Symbol);

                rating.Symbol.Prices = result.DailyPrices;

                decimal rsi = rsiCalculator.Calculate(rating.Symbol, 14, rating.Symbol.Prices.First().PriceDate);
            }           

        }

        private void _FTSE350ExtractorTest_Click(object sender, EventArgs e)
        {
            ISymbolExtractor symbolExtractor = new FTSE350ListExtractor();
            IHistoricPricesExtractor _YahooricesExtractor = new YahooHistoricPriceExtractor();
            RelativeStrengthIndicatorCalculator rsiCalculator = new RelativeStrengthIndicatorCalculator();

            List<string> results = new List<string>();

            //get ftse 350 companies
            List<Symbol> symbols = symbolExtractor.ExtractSymbolsFromUrl("http://shareprices.com/ftse350").Select(
                s => new Symbol(){ Name = s.Replace(".","-") + ".L"}).ToList();

            HistoricPricesExtract result = null;
            decimal rsi;

            foreach (Symbol symbol in symbols)
            {
                result = _YahooricesExtractor.GetHistoricPrices(DateTime.Now.AddYears(-15), DateTime.Today, symbol);

                symbol.Prices = result.DailyPrices;

                if (symbol.Prices != null && symbol.Prices.Count > 15)
                {
                    rsi = rsiCalculator.Calculate(symbol, 14, symbol.Prices.First().PriceDate);

                    results.Add(string.Format("{0}:{1}", rsi, symbol.Name));

                    System.Diagnostics.Debug.WriteLine(symbol.Name);
                }
            }

            IOrderedEnumerable<string> orderedResults = results.OrderByDescending(s => s);

            foreach (var orderedResult in orderedResults)
            {
                System.Diagnostics.Debug.WriteLine(orderedResult);
            }

            //rsi
        }

        private void _BPRSITestButton_Click(object sender, EventArgs e)
        {
            Symbol symbol = new Symbol() { Name = "BP.L" };

            //download BPs price history
            IHistoricPricesExtractor yahooPricesExtractor = new YahooHistoricPriceExtractor();
            HistoricPricesExtract pricesExtract = yahooPricesExtractor.GetHistoricPrices(DateTime.Now.AddYears(-15), DateTime.Today, symbol);

            symbol.Prices = pricesExtract.DailyPrices;

            SmoothedRelativeStrengthIndicatorCalculator rsiCalculator = new SmoothedRelativeStrengthIndicatorCalculator();

            decimal result = rsiCalculator.Calculate(symbol, 20, DateTime.Today);
        }
    }
}
